package cc.rengu.redp.bizimpl.igas.service.impl;

import cc.rengu.redp.bizimpl.bean.UpmpWorkFlowVar;
import cc.rengu.redp.bizimpl.constant.UpmpConstant;
import cc.rengu.redp.bizimpl.constant.UpmpProcessConstant;
import cc.rengu.redp.bizimpl.enums.BizDataAuditStatusEnum;
import cc.rengu.redp.bizimpl.upmp.domain.UpmpSysParam;
import cc.rengu.redp.bizimpl.upmp.service.IUpmpSysParamService;
import cc.rengu.redp.bizimpl.upmp.vo.WaitingToDoVO;
import cc.rengu.redp.bizimpl.utils.Common;
import cc.rengu.redp.bizimpl.utils.DateUtils;
import cc.rengu.redp.bizimpl.utils.RedpUpmpUtil;
import cc.rengu.redp.common.domain.QueryRequest;
import cc.rengu.redp.common.domain.RedpConstant;
import cc.rengu.redp.common.exception.RedpException;
import cc.rengu.redp.common.utils.DateUtil;
import cc.rengu.redp.common.utils.RedpUtil;
import cc.rengu.redp.common.utils.SortUtil;
import cc.rengu.redp.bizimpl.igas.dao.PBinInfoMapper;
import cc.rengu.redp.bizimpl.igas.domain.PBinInfo;
import cc.rengu.redp.bizimpl.igas.service.IPBinInfoService;
import cc.rengu.redp.flowable.service.WorkFlowVar;
import cc.rengu.redp.system.domain.User;
import com.alibaba.fastjson.JSONObject;
import com.baomidou.dynamic.datasource.annotation.DS;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.core.toolkit.StringPool;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.google.common.collect.Maps;
import lombok.extern.slf4j.Slf4j;
import org.flowable.engine.IdentityService;
import org.flowable.engine.RuntimeService;
import org.flowable.engine.TaskService;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Propagation;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.StringUtils;

import java.util.*;

/**
 * @author System
 */
@Service("pBinInfoService")
@Slf4j
@DS("igas")
@Transactional(propagation = Propagation.SUPPORTS, rollbackFor = RedpException.class)
public class PBinInfoServiceImpl extends ServiceImpl<PBinInfoMapper, PBinInfo> implements IPBinInfoService {
    private final static String updateCheckPagePath = "bizimpl/igas/pbininfo/PBinInfoCheck";
    private final static String addCheckPagePath = "bizimpl/igas/pbininfo/PBinInfoCheck";

    @Autowired
    private PBinInfoMapper pBinInfoMapper;

//    @Autowired
//    private IUpmpWorkFlowService upmpWorkFlowService;
    @Autowired
    private RuntimeService runtimeService;
    @Autowired
    private IdentityService identityService;
    @Autowired
    private TaskService taskService;
    @Autowired
    private IUpmpSysParamService upmpSysParamService;

    @Override
    public IPage<PBinInfo> findByPage(QueryRequest request, PBinInfo pBinInfo) throws RedpException {
/*
        List<Task> tasks = taskService.createTaskQuery()
                .processVariableValueEquals("instId", "001")
                .taskCandidateGroup("2")
                .list();
        log.info("You have " + tasks.size() + " tasks:");
        for (int i=0; i<tasks.size(); i++) {
            log.info((i+1) + ") " + tasks.get(i).getName());
            Task task = tasks.get(i);
            task.getProcessInstanceId();
//            log.info(JSONObject.toJSONString(tasks.get(i)));
        }*/

        LambdaQueryWrapper<PBinInfo> lambdaQueryWrapper = new LambdaQueryWrapper<>();
//        lambdaQueryWrapper.select(PBinInfo::getReconSceneId);
        if (!StringUtils.isEmpty(pBinInfo.getIssuerCode())) {
            lambdaQueryWrapper.eq(PBinInfo::getIssuerCode, pBinInfo.getIssuerCode());
        }
        if (!StringUtils.isEmpty(pBinInfo.getBinNo())) {
            lambdaQueryWrapper.like(PBinInfo::getBinNo, pBinInfo.getBinNo());
        }

        Page<PBinInfo> page = new Page<>();
        SortUtil.handlePageSort(request, page, "binNo", RedpConstant.ORDER_DESC, true);
        try {
            IPage<PBinInfo> tbPage = this.page(page, lambdaQueryWrapper);
            //卡BIN列表
            List<PBinInfo> list = tbPage.getRecords();
            list.forEach(t -> {
                //联合主键
                t.setId(t.getIssuerCode().concat(StringPool.PIPE).concat(t.getBinNo()));
            });
            tbPage.setRecords(list);
            return tbPage;
        } catch (Exception e) {
            log.error("查询数据异常", e);
            return null;
        }
    }

    @Override
    public PBinInfo findByUK(String issuerCode, String binNo) {
        PBinInfo pBinInfo = new PBinInfo();
        pBinInfo.setIssuerCode(pBinInfo.getIssuerCode());
        pBinInfo.setBinNo(binNo);
        return pBinInfoMapper.findByUK(pBinInfo);
    }

    @Override
    public void add(PBinInfo pBinInfo) throws RedpException {
        pBinInfoMapper.insert(pBinInfo);
    }

    @Override
    public void update(PBinInfo pBinInfo) throws RedpException {
        UpmpSysParam defaultInst = upmpSysParamService.getById(UpmpConstant.DEAFULT_INST_PARAM_ID);
        //当前用户ID
        String currentUser = String.valueOf(RedpUpmpUtil.getCurrentUser(defaultInst.getPrimaryValue()).getUserId());
        WorkFlowVar workFlowVar = new UpmpWorkFlowVar();
        Map<String, Object> var = Maps.newHashMap();
        var.put(UpmpProcessConstant.VAR_NAME_INST_ID, "001");
        var.put(UpmpProcessConstant.VAR_NAME_ROLE_ID, "2");
        var.put(UpmpProcessConstant.VAR_NAME_PROCESS_REAL_NAME, "卡BIN信息修改");
        //将修改后的数据以JSON串格式存入流程变量，如果表字段过多则不建议存，这里用的是两个varchar2(2000)的字段存储
        var.put(UpmpProcessConstant.VAR_NAME_BIZ_DATA, JSONObject.toJSONString(pBinInfo));
        var.put(UpmpProcessConstant.VAR_NAME_PAGE_PATH, updateCheckPagePath);
        var.put(UpmpProcessConstant.VAR_NAME_AUDIT_STATUS, BizDataAuditStatusEnum.AUDIT_STATUS_UPD_CHECKING.getType());
        workFlowVar.setVarMap(var);

//        String procInstId = upmpWorkFlowService.startProcess(UpmpProcessConstant.DEFAULT_PROCESS_DEFINITION_KEY, currentUser, PBinInfo.class.getSimpleName(), workFlowVar);

//        identityService.setAuthenticatedUserId(currentUser);
//        ProcessInstance pi = runtimeService.startProcessInstanceByKey(
//                "bizCheck",
//                PBinInfo.class.getSimpleName(),
//                var);
//
//        String procInstId =pi.getProcessInstanceId();
//        String procInstId = workFlowService.startProcess("bizCheck",currentUser,PBinInfo.class.getSimpleName(),workFlowVar);
//        log.info("create processInstance ,processInstanceId is: {} ", procInstId);
//        pBinInfoMapper.updateById(pBinInfo);
    }

    @Override
    public void check(WaitingToDoVO taskInfo) throws RedpException {
//        List<NextToDo> nextNodeList = upmpWorkFlowService.getOutComeListByTaskId(taskInfo.getTaskId()) ;
/*
        //获取当前task的nodeId
        String nodeId = upmpWorkFlowService.getNodeIdByTaskId(taskInfo.getTaskId());
        //通过系统参数配置设置当前nodeId对应的下一步需要人工介入的nodeId，这里假设已经从参数配置中取出
        String nextNodeId = "ND02";
        User currentUser = RedpUtil.getCurrentUser();
        UpmpWorkFlowVar workFlowVar = upmpWorkFlowService.getVariable(taskInfo.getTaskId(), UpmpWorkFlowVar.class);
        Map<String, Object> var = workFlowVar.getVarMap();
        if ("ND02".equals(nodeId)) {
            var.put(UpmpProcessConstant.VAR_NAME_APPROVED, taskInfo.isApproved());
            //根据是否审批通过来处理业务数据
            if (taskInfo.isApproved()) {
                String bizData = (String) upmpWorkFlowService.getVariable(taskInfo.getTaskId(), UpmpProcessConstant.VAR_NAME_BIZ_DATA);
                if (!StringUtils.isEmpty(bizData)) {
                    String bizAuditStatus = (String) upmpWorkFlowService.getVariable(taskInfo.getTaskId(), UpmpProcessConstant.VAR_NAME_AUDIT_STATUS);
                    PBinInfo pBinInfo = JSONObject.parseObject(bizData, PBinInfo.class);
                    PBinInfo dbOld = this.findByUK(pBinInfo.getIssuerCode(), pBinInfo.getBinNo());
                    BeanUtils.copyProperties(pBinInfo, dbOld);
                    dbOld.setUpdateTime(DateUtil.getDateFormat(new Date(), DateUtil.FULL_TIME_WITH_MILL_SPLIT_PATTERN));
                    if (BizDataAuditStatusEnum.AUDIT_STATUS_UPD_CHECKING.getType().equals(bizAuditStatus)) {
                        dbOld.setMaintainFlag("U");
                    } else if (BizDataAuditStatusEnum.AUDIT_STATUS_ADD_CHECKING.getType().equals(bizAuditStatus)) {
                        dbOld.setMaintainFlag("A");
                    } else if (BizDataAuditStatusEnum.AUDIT_STATUS_CANCEL_CHECKING.getType().equals(bizAuditStatus)) {
                        dbOld.setMaintainFlag("D");
                    }
                    this.baseMapper.updateByUK(dbOld);
                }
            }
        } else if ("ND02".equals(nextNodeId)) {
            var.put(UpmpProcessConstant.VAR_NAME_SEC_ROLE_ID, "3");
            var.put(UpmpProcessConstant.VAR_NAME_APPROVED, taskInfo.isApproved());
        }
        upmpWorkFlowService.setComment(taskInfo.getProcInstId(), taskInfo.getTaskId(), currentUser.getUsername(), taskInfo.getComment());
        upmpWorkFlowService.completeTaskByTaskId(taskInfo.getTaskId(), workFlowVar);
        */
    }

    @Override
    public Map<String, Object> getTblTxnInfSelect2List(String q, QueryRequest request) {

        if (null == q) {
            return null;
        }
        q = q.replaceAll("&amp;", "&");

        String issuerCodeOrName = "";
        String[] param = q.split("&");
        if (null != param && param.length > 0) {
            issuerCodeOrName = param[0];
        }

        try {
            QueryWrapper<PBinInfo> queryWrapper = new QueryWrapper<>();
            queryWrapper.select("DISTINCT ISSUER_CODE, ISSUER_NAME");

            if (org.apache.commons.lang3.StringUtils.isNotEmpty(issuerCodeOrName)) {
                String finalIssuerCodeOrName = issuerCodeOrName;
                queryWrapper.and(qw -> qw.lambda().like(PBinInfo::getIssuerCode, finalIssuerCodeOrName).or().like(PBinInfo::getIssuerName, finalIssuerCodeOrName));
            }


            Page<PBinInfo> page = new Page<>();
            SortUtil.handlePageSort(request, page, true);
            Page<PBinInfo> page1 = this.page(page, queryWrapper);
            List<PBinInfo> listx = page1.getRecords();

            Map<String, Object> maps = new HashMap<String, Object>();
            Map<String, String> map = new HashMap<String, String>();
            List<Object> list = new ArrayList<Object>();
            if (listx != null) {
                for (int i = 0; i < listx.size(); i++) {
                    PBinInfo org = listx.get(i);
                    map = new HashMap<String, String>();
                    map.put("id", org.getIssuerCode());
                    map.put("name", org.getIssuerName());

                    list.add(map);
                }
                maps.put("results", list);
                maps.put("total", page.getTotal());
                int pageIndex = Common.isBlank(request.getPageNum()) ? 1 : request.getPageNum();
                if (pageIndex == page1.getTotal()) {
                    maps.put("more", false);
                } else {
                    maps.put("more", true);
                }
            }
            return maps;

        } catch (Exception e) {
            log.error("查询发卡机构出现异常", e);
            return null;
        }
    }

    @Override
    public void addBinInfo(PBinInfo binInfo) {
        binInfo.setMaintainFlag("A");
        binInfo.setCreateTime(DateUtils.formatDate(new Date(), "yyyy-MM-dd HH:mm:ss.SSS"));
        binInfo.setUpdateTime(DateUtils.formatDate(new Date(), "yyyy-MM-dd HH:mm:ss.SSS"));

        this.baseMapper.insert(binInfo);
    }

    @Override
    public void updateBinInfo(PBinInfo binInfo) {
        String flag = binInfo.getOptFlag();

        if ("upd".equals(flag)) {
            binInfo.setMaintainFlag("U");
            binInfo.setUpdateTime(DateUtils.formatDate(new Date(), "yyyy-MM-dd HH:mm:ss.SSS"));
        } else if ("cancel".equals(flag)){
            binInfo.setBinStatus("N");
            binInfo.setMaintainFlag("D");
            binInfo.setUpdateTime(DateUtils.formatDate(new Date(), "yyyy-MM-dd HH:mm:ss.SSS"));
        }

        LambdaUpdateWrapper<PBinInfo> wrapper = new LambdaUpdateWrapper<>();
        wrapper.eq(PBinInfo::getIssuerCode, binInfo.getIssuerCode()).eq(PBinInfo::getBinNo, binInfo.getBinNo());

        baseMapper.update(binInfo, wrapper);

    }

}
